from numbers import Number
from typing import List, Literal

from modules.amis.component.base import BaseSchema, ActionType, Level, Size, Placement, Trigger, Api, Toast, SchemaNode, \
    SchemaMessage, SchemaApi, Action, Position, Function, LeftAndRight, SchemaIcon, SchemaType, SchemaExpression, \
    SchemaName
from modules.amis.component.feedback import Dialog, Feedback


class Button(Action):
    """
    按钮

    Args:
        reload:  重新加载指定的组件  比如："reload": "myForm.group",
        target: 刷新其他组件, 需要刷新的目标组件名字（组件的name值，自己配置的），多个请用 , 号隔开。
        icon: 实现按钮显示图标, 也可以是 url 地址；如果label配置为空字符串，可以只显示icon
        confirmText: 操作前确认; 可以通过配置confirmText，实现在任意操作前，弹出提示框确认是否进行该操作。同时可以通过配置 confirmTitle 来设置弹窗标题
    """

    def __init__(self,
                 label: str = None,
                 actionType: ActionType = None,
                 level: Level = None,
                 size: Size = None,
                 api: Api = None,
                 tooltip: str = None,
                 icon: str = None,
                 tooltipPlacement: Placement = None,
                 tooltipTrigger: Trigger = None,
                 disabled: bool = None,
                 disabledTip: str = None,
                 block: bool = None,
                 loading: bool = None,
                 loadingOn: str = None,
                 className: str = None,
                 dialog: Dialog = None,
                 toast: Toast = None,
                 reload: str = None,
                 target: str = None,
                 feedback: Feedback = None,
                 confirmText: str = None,
                 confirmTitle: str = None,
                 **kwargs
                 ):
        super().__init__()
        self.type = "button"
        self.label = label
        self.actionType: ActionType = actionType
        self.level: Level = level
        self.size: Size = size
        self.api: Api = api
        self.icon: str = icon
        self.tooltip: str = tooltip
        self.tooltipPlacement: Placement = tooltipPlacement
        self.tooltipTrigger: Trigger = tooltipTrigger
        self.disabled: bool = disabled
        self.disabledTip: str = disabledTip
        self.block: bool = block
        self.loading: bool = loading
        self.loadingOn: str = loadingOn
        self.className: str = className
        self.dialog: Dialog = dialog
        self.reload: str = reload
        self.toast: Toast = toast
        self.target: str = target
        self.feedback: Feedback = feedback
        self.confirmText: str = confirmText
        self.confirmTitle: str = confirmTitle
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class AjaxButton(Button):
    """
    ajax 请求
    """

    def __init__(self,
                 api: str = "",
                 redirect: str = "",
                 feedback: Feedback = None,
                 **kwargs
                 ):
        super().__init__()
        self.actionType = ActionType.ajax
        self.api: str = api
        self.redirect: str = redirect
        self.feedback: Feedback = feedback
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class SaveAsButton(Button):
    """
    保存到本地

    Args:
        api: 下载api
        fileName: 默认会自动取 url 中的文件名，如果没有的话就需要指定
    """

    def __init__(self,
                 api: str = "",
                 fileName: str = "",
                 **kwargs
                 ):
        super().__init__()
        self.actionType = ActionType.saveAs
        self.api: str = api
        self.fileName: str = fileName
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class DownloadButton(Button):
    """
    下载请求

    Args:
        api: 下载api
    """

    def __init__(self,
                 api: str = "",
                 **kwargs
                 ):
        super().__init__()
        self.actionType = ActionType.download
        self.api: str = api
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class EmailButton(Button):
    """
    发送邮件

    Args:
        to: 收件人邮箱，可用 ${xxx} 取值。
        cc: 抄送邮箱，可用 ${xxx} 取值。
        bcc: 匿名抄送邮箱，可用 ${xxx} 取值。
        subject: 邮件主题，可用 ${xxx} 取值。
        body: 邮件正文，可用 ${xxx} 取值。
    """

    def __init__(self,
                 to: str = "",
                 cc: str = "",
                 bcc: str = "",
                 subject: str = "",
                 body: str = "",
                 **kwargs
                 ):
        super().__init__()
        self.actionType = ActionType.email
        self.to: str = to
        self.cc: str = cc
        self.bcc: str = bcc
        self.subject: str = subject
        self.body: str = body
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class UrlButton(Button):
    """
    直接跳转
    """

    def __init__(self,
                 url: str = "",
                 blank: bool = False,
                 **kwargs
                 ):
        super().__init__()
        self.actionType = ActionType.url
        self.url: str = url
        self.blank: bool = blank
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class LinkButton(Button):
    """
    单页跳转
    """

    def __init__(self,
                 link: str = "",
                 **kwargs
                 ):
        super().__init__()
        self.actionType = ActionType.link
        self.link: str = link
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class CopyButton(Button):
    """
    复制文本

    Args:
        content: 指定复制的内容。可用 ${xxx} 取值。
    """

    def __init__(self,
                 content: str = "",
                 **kwargs
                 ):
        super().__init__()
        self.actionType = ActionType.copy
        self.content: str = content
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class ClearButton(Button):
    """
    清空表单数据
    """

    def __init__(self,
                 **kwargs
                 ):
        super().__init__()
        self.type = "button"
        self.actionType = ActionType.clear
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class ResetButton(Button):
    """
    重置表单数据
    """

    def __init__(self,
                 **kwargs
                 ):
        super().__init__()
        self.type = "reset"
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class SubmitButton(Button):
    def __init__(self,
                 **kwargs
                 ):
        super().__init__()
        self.type = "submit"
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class ResetAndSubmitButton(Button):
    """
        重置表单并提交
    """

    def __init__(self,
                 **kwargs
                 ):
        super().__init__()
        self.type = "button"
        self.actionType = "reset-and-submit"
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class ClearAndSubmitButton(Button):
    """
    清空表单并提交
    """

    def __init__(self,
                 **kwargs
                 ):
        super().__init__()
        self.type = "button"
        self.actionType = "clear-and-submit"
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value

class Service(BaseSchema):
    """
       Service 功能型容器

       amis 中部分组件，作为展示组件，自身没有使用接口初始化数据域的能力，例如：Table、Cards、List等，他们需要使用某些配置项，例如source，通过数据映射功能，在当前的 数据链 中获取数据，并进行数据展示。

        而Service组件就是专门为该类组件而生，它的功能是：配置初始化接口，进行数据域的初始化，然后在Service内容器中配置子组件，这些子组件通过数据链的方法，获取Service所拉取到的数据

    Args:
        type:	string	"service"	指定为 service 渲染器
        className:	string		外层 Dom 的类名
        body:	SchemaNode		内容容器
        api:	API		初始化数据域接口地址
        ws:	string		WebScocket 地址
        dataProvider:	string | Record<"inited" | "onApiFetched" | "onSchemaApiFetched" | "onWsFetched", string>		数据获取函数
        initFetch:	boolean		是否默认拉取
        schemaApi:	API		用来获取远程 Schema 接口地址
        initFetchSchema:	boolean		是否默认拉取 Schema
        messages:	Object		消息提示覆写，默认消息读取的是接口返回的 toast 提示文字，但是在此可以覆写它。
        messages.fetchSuccess:	string		接口请求成功时的 toast 提示文字
        messages.fetchFailed:	string	"初始化失败"	接口请求失败时 toast 提示文字
        interval:	number		轮询时间间隔，单位 ms(最低 1000)
        silentPolling:	boolean	false	配置轮询时是否显示加载动画
        stopAutoRefreshWhen:	表达式		配置停止轮询的条件
        showErrorMsg:	boolean	true	是否以 Alert 的形式显示 api 接口响应的错误信息，默认展示	2.8.1
    """

    def __init__(self,
                 name: SchemaName = "",
                 body: SchemaNode = None,
                 className: str = "",
                 api: SchemaApi = None,
                 ws: str = "",
                 dataProvider: str = "",
                 initFetch: bool = None,
                 schemaApi: SchemaApi = None,
                 initFetchSchema: bool = None,
                 messages: SchemaMessage = None,
                 interval: Number = None,
                 silentPolling: bool = None,
                 stopAutoRefreshWhen: SchemaExpression = None,
                 showErrorMsg: bool = None,
                 **kwargs
                 ):
        super().__init__()
        self.type = "service"
        # 组件名字，这个名字可以用来定位，用于组件通信
        self.name: SchemaName = name
        # 内容区域
        self.body: SchemaNode = body
        self.className: str = className
        # 页面初始化的时候，可以设置一个 API 让其取拉取，发送数据会携带当前 data 数据（包含地址栏参数），获取得数据会合并到 data 中，供组件内使用。
        self.api: SchemaApi = api
        # WebScocket 地址，用于实时获取数据
        self.ws: str = ws
        # 通过调用外部函数来获取数据
        self.dataProvider: str = dataProvider
        # 是否默认就拉取？
        self.initFetch: bool = initFetch
        # 用来获取远程 Schema 的 api
        self.schemaApi: SchemaApi = schemaApi
        # 是否默认加载 schemaApi
        self.initFetchSchema: bool = initFetchSchema
        self.messages: SchemaMessage = messages
        # 是否轮询拉取
        self.interval: Number = interval
        # 是否静默拉取
        self.silentPolling: bool = silentPolling
        # 关闭轮询的条件。
        self.stopAutoRefreshWhen: SchemaExpression = stopAutoRefreshWhen
        # 是否以Alert的形式显示api接口响应的错误信息，默认展示
        self.showErrorMsg: bool = showErrorMsg
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class BreadcrumbDropdown(BaseSchema):
    def __init__(self,
                 label: str = "",
                 href: str = "",
                 icon: str = "",
                 **kwargs,
                 ):
        super().__init__()
        self.label: str = label
        self.href: str = href
        self.icon: str = icon
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value

class BreadcrumbItem(BaseSchema):
    def __init__(self,
                 label: str = "",
                 href: str = "",
                 icon: str = "",
                 dropdown: List[BreadcrumbDropdown] = None,
                 **kwargs,
                 ):
        super().__init__()
        self.label: str = label
        self.href: str = href
        self.icon: str = icon
        self.dropdown: List[BreadcrumbDropdown] = dropdown
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value

class Breadcrumb(BaseSchema):
    """
    Breadcrumb 面包屑

    Args:
        className:	string		外层类名
        itemClassName:	string		导航项类名
        separatorClassName:	string		分割符类名
        dropdownClassName:	string		下拉菜单类名
        dropdownItemClassName:	string		下拉菜单项类名
        separator:	string		分隔符
        labelMaxLength:	number	16	最大展示长度
        tooltipPosition:	top | bottom | left | right	top	浮窗提示位置
        source:	string		动态数据
        items[].label:	string		文本
        items[].href:	string		链接
        items[].icon:	string		图标
        items[].dropdown:	dropdown[]		下拉菜单，dropdown[]的每个对象都包含label、href、icon属性
    """
    def __init__(self,
                 className: str = "",
                 itemClassName: str = "",
                 dropdownClassName: str = "",
                 dropdownItemClassName: str = "",
                 separator: str = "",
                 separatorClassName: str = "",
                 labelMaxLength: Number = None,
                 tooltipPosition: Position = None,
                 source: str = "",
                 items: List[BreadcrumbItem] = None,
                 **kwargs,
                 ):
        super().__init__()
        self.type = "breadcrumb"
        self.className: str = className
        self.itemClassName: str = itemClassName
        self.separatorClassName: str = separatorClassName
        self.dropdownClassName: str = dropdownClassName
        self.dropdownItemClassName: str = dropdownItemClassName
        self.separator: str = separator
        self.labelMaxLength: Number = labelMaxLength
        self.tooltipPosition: Position = tooltipPosition
        self.source: str = source
        self.items: List[BreadcrumbItem] = items
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class Custom(BaseSchema):
    """
    Custom 自定义组件

    Args:
        type:	'custom'
        id:	string		节点 id
        name:	string		节点 名称
        className:	string		节点 class
        inline:	boolean	false	默认使用 div 标签，如果 true 就使用 span 标签
        html:	string		初始化节点 html
        onMount:	string	Function	节点初始化之后调的用函数
        onUpdate:	string	Function	数据有更新的时候调用的函数
        onUnmount:	string	Function	节点销毁的时候调用的函数
    """
    def __init__(self,
                 id: str = None,
                 label: str = None,
                 name: str = None,
                 className: str = None,
                 inline: bool = False,
                 html: str = None,
                 onMount: Function = None,
                 onUpdate: Function = None,
                 onUnmount: Function = None,
                 **kwargs,
                 ):
        super().__init__()
        self.type = "custom"
        self.id: str = id
        self.label: str = label
        self.name: str = name
        self.className: str = className
        self.inline: bool = inline
        self.html: str = html
        self.onMount: Function = onMount
        self.onUpdate: Function = onUpdate
        self.onUnmount: Function = onUnmount
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value


class DropDownButton(BaseSchema):
    """
    DropDownButton 下拉菜单

    Args:
        type:	string	dropdown-button	类型
        label:	string		按钮文本
        className:	string		外层 CSS 类名
        btnClassName:	string		按钮 CSS 类名
        menuClassName:	string		下拉菜单 CSS 类名
        block:	boolean		块状样式
        size:	string		尺寸，支持'xs'、'sm'、'md' 、'lg'
        align:	string		位置，可选'left'或'right'
        buttons:	Array<DropdownButton>		配置下拉按钮
        iconOnly:	boolean		只显示 icon
        defaultIsOpened:	boolean		默认是否打开
        closeOnOutside:	boolean	true	点击外侧区域是否收起
        closeOnClick:	boolean	false	点击按钮后自动关闭下拉菜单
        trigger:	click 或 hover	click	触发方式
        hideCaret:	boolean	false	隐藏下拉图标
    """
    def __init__(self,
                 label: str = "",
                 name: str = "",
                 body: SchemaNode = "",
                 className: str = "",
                 btnClassName: str = "",
                 menuClassName: str = "",
                 block: bool = False,
                 size: Size = None,
                 align: LeftAndRight = None,
                 iconOnly: bool = False,
                 rightIcon: SchemaIcon = "",
                 defaultIsOpened: bool = False,
                 closeOnOutside: bool = True,
                 closeOnClick: bool = False,
                 trigger: Literal["click", "hover"] = "click",
                 hideCaret: bool = False,
                 overlayPlacement: str = "",
                 buttons: List[SchemaNode] = None,
                 **kwargs,
                 ):
        super().__init__()
        self.type: SchemaType = "dropdown-button"
        self.label: str = label
        self.name: str = name
        self.body: SchemaNode = body
        self.className: str = className
        self.btnClassName: str = btnClassName
        self.menuClassName: str = menuClassName
        self.block: bool = block
        self.size: Size = size
        self.align: LeftAndRight = align
        self.iconOnly: bool = iconOnly
        self.defaultIsOpened: bool = defaultIsOpened
        self.closeOnOutside: bool = closeOnOutside
        self.closeOnClick: bool = closeOnClick
        self.trigger: Literal["click", "hover"] = trigger
        self.hideCaret: bool = hideCaret
        self.rightIcon: SchemaIcon = rightIcon
        self.overlayPlacement: str = overlayPlacement
        self.buttons: List[SchemaNode] = buttons
        for _key, _value in kwargs.items():
            self.__dict__[_key] = _value